package me.zhengjie.timing.task;

import lombok.RequiredArgsConstructor;
import me.zhengjie.WcsReport.BuzzerService;
import me.zhengjie.agvSend.AgvSendService;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.entity.WcsDeliveryMission;
import me.zhengjie.pojo.entity.WcsLineEdgeWarehouse;
import me.zhengjie.sqlservice.WcsDeliveryMissionService;
import me.zhengjie.sqlservice.WcsLineEdgeWarehouseService;
import me.zhengjie.utility.IdWorker;
import me.zhengjie.utility.liftState.PriorityEnum;
import me.zhengjie.utility.state.TaskStatus;
import me.zhengjie.utility.state.TaskType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class DeliveryTiming {
    private static final Logger outbound = LoggerFactory.getLogger("wcsOutbound");

    private final WcsDeliveryMissionService wcsDeliveryMissionService;

    private final WcsLineEdgeWarehouseService wcsLineEdgeWarehouseService;

    private final AgvSendService agvSendService;

    private final IdWorker idWorker;

    private final BuzzerService buzzerService;

    @Transactional
    @Scheduled(fixedDelay = 1000)
    public void deliver(){
        List<WcsDeliveryMission> wcsDeliveryMissionList = wcsDeliveryMissionService.selectMissionStatus(TaskStatus.Task_create.getStatus());
        if (!wcsDeliveryMissionList.isEmpty()){
            for (WcsDeliveryMission wcsDeliveryMission : wcsDeliveryMissionList) {
                String destination = wcsDeliveryMission.getDestination();
                String source = wcsDeliveryMission.getSource();
                String deliveryCode = wcsDeliveryMission.getDeliveryCode();
                String floor = wcsDeliveryMission.getFloor();
                List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouses = wcsLineEdgeWarehouseService.selectRegionStatusIsNull(floor,destination, TaskStatus.LINE_EDGE_WAREHOUSE_IDLE.getStatus());
                if (!wcsLineEdgeWarehouses.isEmpty()){
                    WcsLineEdgeWarehouse wcsLineEdgeWarehouse = wcsLineEdgeWarehouses.get(0);
                    String storageCode = wcsLineEdgeWarehouse.getStorageCode();
                    //有终点储位，下发任务给agv
                    //储位绑定栈板
                    CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
                    carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
                    carrierUnbindDto.setSlotCode(source);
                    carrierUnbindDto.setCarrierCategory("PALLET");
                    carrierUnbindDto.setCarrierType("1");
                    carrierUnbindDto.setInvoke(TaskType.BIND.getMessage());
                    agvSendService.carrierUnbind(carrierUnbindDto);
                    AgvTaskSubmitDto agvTaskSubmitDto = new AgvTaskSubmitDto();
                    //todo 任务类型，根据现场情况来定
                    agvTaskSubmitDto.setTaskType(TaskType.PF_FMR_COMMON.getMessage());
                    ArrayList<TargetRoute> targetRouteList = new ArrayList<>();
                    TargetRoute targetRoute = new TargetRoute();
                    TargetRoute targetRoutes = new TargetRoute();
                    //添加起点
                    targetRoute.setSeq(0);
                    targetRoute.setType(TaskType.STORAGE.getMessage());
                    targetRoute.setCode(source);
                    //添加终点
                    targetRoutes.setSeq(1);
                    targetRoutes.setType(TaskType.SITE.getMessage());
                    targetRoutes.setCode(storageCode);
                    targetRouteList.add(targetRoute);
                    targetRouteList.add(targetRoutes);
                    agvTaskSubmitDto.setTargetRoute(targetRouteList);
                    agvTaskSubmitDto.setRobotTaskCode(deliveryCode);
                    agvTaskSubmitDto.setInitPriority(PriorityEnum.FOUR.getWeight());
                    String taskCode = agvSendService.agvTaskSubmit(agvTaskSubmitDto);
                    if (taskCode != null) {
                        //修改任务状态为1
                        boolean b1 = wcsDeliveryMissionService.updateMissionStatus(deliveryCode, TaskStatus.task_send.getStatus());
                        //将线边仓储位预定
                        boolean b = wcsLineEdgeWarehouseService.updateStatusIsAgv(storageCode,null, TaskStatus.LINE_EDGE_WAREHOUSE_RESERVED.getStatus(), 1);
                        if (!b) {
                            outbound.error("数据库异常，修改线边仓储位失败");
                            throw new RuntimeException("数据库异常，修改线边仓储位失败");
                        }
                    }
                }
            }

        }



        //线边仓储位监控
        List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouses = wcsLineEdgeWarehouseService.selectAll();
        if (!wcsLineEdgeWarehouses.isEmpty()){
            for (WcsLineEdgeWarehouse wcsLineEdgeWarehouse : wcsLineEdgeWarehouses) {
                Integer ccdStatus = wcsLineEdgeWarehouse.getCcdStatus();
                Integer status = wcsLineEdgeWarehouse.getStatus();
                String storageCode = wcsLineEdgeWarehouse.getStorageCode();
                Integer id = wcsLineEdgeWarehouse.getId();
                String storageCode1 = wcsLineEdgeWarehouse.getStorageCode();
                String goodType = wcsLineEdgeWarehouse.getGoodType();
                if (ccdStatus ==1 && status == 0){
                    //人员放货
                    wcsLineEdgeWarehouseService.updateManualFeeding(id,storageCode+"人工放料", TaskStatus.LINE_EDGE_WAREHOUSE_MANUAL_LOAD.getStatus());
                }else if (ccdStatus ==0 && status !=0 && status !=1 ){
                    //货物被人员拉走，清空储位
                    wcsLineEdgeWarehouseService.updateStatusIsAgv(storageCode1,null,TaskStatus.LINE_EDGE_WAREHOUSE_IDLE.getStatus(),0,0);
                    if (TaskType.STORAGE_TYPE_THREE_FLOOR_EMPTY_PALLET.getMessage().equals(goodType)){
                        //修改数量为0
                        wcsLineEdgeWarehouseService.updateEmptyTrayQuantityStatus(storageCode1, 0, TaskStatus.LINE_EDGE_WAREHOUSE_IDLE.getStatus());
                    }
                }
            }
        }

        //查询区域都有货，下发蜂鸣器报警
        List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouseList = wcsLineEdgeWarehouseService.selectAll();
        Set<String> regionSet = wcsLineEdgeWarehouseList.stream().distinct().map(WcsLineEdgeWarehouse::getRegion).collect(Collectors.toSet());

        for (String region : regionSet) {
            if (region !=null){
                List<WcsLineEdgeWarehouse> wcsLineEdgeWarehouses1 = wcsLineEdgeWarehouseService.selectRegionContainerCodeisNotNull(region);
                List<WcsLineEdgeWarehouse> LineEdgeWarehousesList = wcsLineEdgeWarehouseService.selectRegion(region);
                List<WcsLineEdgeWarehouse> wcsLineEdgeWarehousesNull = wcsLineEdgeWarehouseService.selectRegionContainerCodeIsNull(region);

                if (!LineEdgeWarehousesList.isEmpty()){
//                    outbound.info("区域：{}根据区域查询有货数量：{},数据：{}",region,wcsLineEdgeWarehouses1.size(),wcsLineEdgeWarehouses1);
//                    outbound.info("查询区域数量：{},空栈板数量：{},有栈板数量：{}",LineEdgeWarehousesList.size(),wcsLineEdgeWarehousesNull.size(),wcsLineEdgeWarehouses1.size());
                    Integer buzzerStatus = LineEdgeWarehousesList.get(0).getBuzzerStatus();
                    //根据区域查询到所有储位名称
                    Set<String> storageCodeSet = LineEdgeWarehousesList.stream().map(WcsLineEdgeWarehouse::getStorageCode).collect(Collectors.toSet());
                    List<WcsDeliveryMission> wcsDeliveryMissions = wcsDeliveryMissionService.selectDestinationSNotMissionStatus(storageCodeSet,TaskStatus.Task_complete.getStatus());
                    if (LineEdgeWarehousesList.size() == wcsLineEdgeWarehouses1.size() && buzzerStatus ==0 && !wcsDeliveryMissions.isEmpty()){
                        //通知峰鸣器报警
                        String buzzerIp = wcsLineEdgeWarehouses1.get(0).getBuzzerIp();
                        BuzzerDto buzzerDto = new BuzzerDto();
                        buzzerDto.setSite(1);
                        buzzerDto.setRed(1);
                        buzzerDto.setBuzzer(1);
                        buzzerService.buzzerSend(buzzerDto,buzzerIp);
                        wcsLineEdgeWarehouseService.updateBuzzerStatus(region,1);
                    }
                    if ( (LineEdgeWarehousesList.size() != wcsLineEdgeWarehouses1.size() && buzzerStatus == 1)){
                        //解除峰鸣器报警
                        String buzzerIp = LineEdgeWarehousesList.get(0).getBuzzerIp();
                        BuzzerDto buzzerDto = new BuzzerDto();
                        buzzerDto.setSite(1);
                        buzzerDto.setRed(0);
                        buzzerDto.setBuzzer(0);
                        buzzerService.buzzerSend(buzzerDto,buzzerIp);
                        wcsLineEdgeWarehouseService.updateBuzzerStatus(region,0);
                    }
                }
            }
        }

        //查询一楼三楼异常区数量，上报给单片机
        Integer oneSize = wcsLineEdgeWarehouseService.anomalyAreaGtThreeSize(TaskType.STORAGE_TYPE_ONE_FLOOR_NEW_ABNORMAL.getMessage());
        Integer threeSize = wcsLineEdgeWarehouseService.anomalyAreaGtThreeSize(TaskType. STORAGE_TYPE_THREE_FLOOR_NEW_ABNORMAL.getMessage());
        if (oneSize != 0 ){
            //发送单片机一楼异常区数量
            McuDto mcuDto = new McuDto();
            ArrayList<McuCount> mcuCounts = new ArrayList<>();
            McuCount mcuCount = new McuCount();
            mcuCount.setCount(oneSize);
            mcuCounts.add(mcuCount);
            mcuDto.setDetails(mcuCounts);
            buzzerService.mcuSend(mcuDto,"127.0.0.1:0000");
        }
        if (threeSize != 0){
            //发送单片机三楼异常区数量
            McuDto dto = new McuDto();
            ArrayList<McuCount> counts = new ArrayList<>();
            McuCount count = new McuCount();
            count.setCount(threeSize);
            counts.add(count);
            dto.setDetails(counts);
            buzzerService.mcuSend(dto,"127.0.0.1:0000");
        }
    }
}
